import { WebGLRenderer, Scene, PerspectiveCamera, Raycaster, Vector2, PointLight } from 'three'
import { CSS2DRenderer, CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer.js'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'

import { cube } from './TBaseObject'
import * as TWEEN from 'three/examples/jsm/libs/tween.module.js'

// 实例化相机
export const camera = new PerspectiveCamera(75, window.innerWidth / window.innerHeight, 10, 1500)
camera.position.x = 0
camera.position.y = 50
camera.position.z = 50

export class ThreeEngine {
  dom = null // 挂载的 DOM
  scene = null // 场景
  renderer = null
  // 构造器函数
  constructor(dom) {
    let scene = new Scene() // 实例化场景
    this.scene = scene

    // scene.add(gui)

    //添加射线监听器
    const pointer = new Vector2()
    const raycaster = new Raycaster()
    let currentPointed = []
    function onPointerMove(event) {
      // calculate pointer position in normalized device coordinates
      // (-1 to +1) for both components

      pointer.x = (event.clientX / window.innerWidth) * 2 - 1
      pointer.y = -(event.clientY / window.innerHeight) * 2 + 1
      raycaster.setFromCamera(pointer, camera)
      let arr = raycaster.intersectObjects(scene.children)
      arr = arr.filter((d) => d.object.userData.clickable)

      const intersects = [...new Map(arr.map((item) => [item.object.name, item])).values()]
      //mesh自动下沉
      let meshes = scene.getObjectsByProperty('type', 'Mesh')
      meshes.forEach((m) => {
        if (!currentPointed.filter((p) => p.name == m.name)) {
          if (m.userData.clickable && m._mouseentered) {
            if (m && m.position.z == m._oringinalY + 6) {
              m._mouseentered = false
              const tween = new TWEEN.Tween(m.position)
              tween.to({ z: 0 }, 500)
              // tween.easing(TWEEN.Easing.Bounce.Out)
              tween.start()
            }
          }
        }
      })
      if (intersects.length > 0) {
        console.log(intersects)

        if (intersects[0].object.userData.clickable) {
          // if(intersected._oringinalY){
          //   intersected.position.z = intersected._oringinalY
          // }
          let intersected = intersects[0].object
          let currentIndex = null
          if (
            !currentPointed.filter((p, i) => {
              if (
                p.name != intersected.name
              ) {
                currentIndex = i
              }
            })
          ) {
            currentPointed.splice(currentIndex, 1)
          }

          currentPointed.forEach(m=>{
            if (m && m.position.z == m._oringinalY + 6) {
              m._mouseentered = false
              const tween = new TWEEN.Tween(m.position)
              tween.to({ z: 0 }, 500)
              // tween.easing(TWEEN.Easing.Bounce.Out)
              tween.start()
            }
          })

          if (!intersected._mouseentered && intersected.position.z == 0) {
            intersected._mouseentered = true
            intersected._oringinalY = intersected.position.z
            const tween = new TWEEN.Tween(intersected.position)
            tween.to({ z: intersected._oringinalY + 6 }, 500)
            tween.easing(TWEEN.Easing.Bounce.Out)
            tween.start()
            currentPointed.push(intersected)
          }
        }
      }
    }
    function onPointerClick(event) {
      // calculate pointer position in normalized device coordinates
      // (-1 to +1) for both components

      pointer.x = (event.clientX / window.innerWidth) * 2 - 1
      pointer.y = -(event.clientY / window.innerHeight) * 2 + 1

      raycaster.setFromCamera(pointer, camera)
      let arr = raycaster.intersectObjects(scene.children)
      arr = arr.filter((d) => d.object.userData.clickable)

      const intersects = [...new Map(arr.map((item) => [item.object.name, item])).values()]

      if (intersects.length > 0) {
        console.log(intersects)

        if (intersects[0].object.userData.clickable) {
          let intersected = intersects[0].object
          if (!intersected._selected) {
            intersected._selected = true
            intersected._oringinalColor = intersected.material.color.getHex()
            intersected.material.color.set(0xff0000)

            let c = cube.clone()

            let { x, y, z } = intersected.geometry.boundingSphere.center
            const { x: cx, y: cy, z: cz } = camera.position
            // if (scene && c) {
            //    // 设置模型的lookAt
            //   c.lookAt(cx,cy,cz)
            // }
            c.position.set(x, y, 0)
            intersected.add(c)

            //动画
            const tween = new TWEEN.Tween(c.position)
            tween.to({ z: c.geometry.parameters.depth }, 500)
            tween.easing(TWEEN.Easing.Bounce.Out)
            tween.start()

            const div = document.createElement('div')
            div.style.color = '#fff'
            div.style.fontSize = '12px'
            div.style.textShadow = '1px 1px 2px #047cd6'
            div.textContent = intersected.name + ':' + (Math.random() * 51234 + 18005).toFixed(0)
            const label = new CSS2DObject(div)
            c.add(label)
          } else {
            intersected._selected = false
            intersected.material.color.set(intersected._oringinalColor)
            intersected.children[0].children[0].removeFromParent()
            intersected.children[0].removeFromParent()
          }
        }
      }
    }

    window.addEventListener('click', onPointerClick)
    window.addEventListener('mousemove', onPointerMove)

    const labelRenderer = new CSS2DRenderer()
    labelRenderer.domElement.style.position = 'absolute'
    labelRenderer.domElement.style.top = '0px'
    labelRenderer.domElement.style.pointerEvents = 'none'
    labelRenderer.setSize(window.innerWidth, window.innerHeight)
    document.getElementById('map').appendChild(labelRenderer.domElement)

    const renderer = new WebGLRenderer({ alpha: true })
    this.renderer = renderer
    renderer.setClearColor('#409EFF', 0.5)
    renderer.setSize(window.innerWidth, window.innerHeight)
    document.getElementById('map').appendChild(renderer.domElement)

    //添加控制器
    const controls = new OrbitControls(camera, renderer.domElement)
    controls.update()
    const animate = () => {
      requestAnimationFrame(animate)
      controls.update()
      renderer.render(scene, camera)
      labelRenderer.render(scene, camera)
      TWEEN.update()
    }
    animate()
    window.addEventListener('resize', () => {
      camera.aspect = window.innerWidth / window.innerHeight
      camera.updateProjectionMatrix()
      renderer.setSize(window.innerWidth, window.innerHeight)
      labelRenderer.setSize(window.innerWidth, window.innerHeight)
    })

    this.dom = dom

    //轨道控制器
  }
  /**
   * 向场景中添加模型
   * @param  {...any} object 模型列表
   */
  addObject(...object) {
    object.forEach((elem) => {
      this.scene.add(elem) // 场景添加模型
    })
  }
  getRenderer() {
    return this.renderer
  }
}
